﻿Imports Microsoft.VisualBasic.Strings
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.Drawing.Imaging

Imports Smart2000


'Imports AForge
'Imports AForge.Video
Imports AForge.Video.DirectShow
'Imports AForge.Imaging

Public Class frmMain

    Public adjustForm As frmAdjust

    Public gCheckFrame As Graphics

    Private gateStatus As Long = 0

    Public WithEvents videoSource As VideoCaptureDevice
    Public CaptureFrame As Bitmap
    Public videoDevices As FilterInfoCollection
    Public myVideoCapabilities As VideoCapabilities

    Public bSampleImageInit As Boolean = False

    Public AdminCheck As Boolean = False

    Public areaPhase1 As AreaInfo
    Public areaPhase2 As AreaInfo
    Public areaPhase3 As AreaInfo
    Public areaPhase4 As AreaInfo
    Public areaPhaseCenter As AreaInfo

    Private gateID(3) As Long
    Private gateCount As Long = 0

    Public areaForPaintPhase1 As AreaInfo
    Public areaForPaintPhase2 As AreaInfo
    Public areaForPaintPhase3 As AreaInfo
    Public areaForPaintPhase4 As AreaInfo
    Public areaForPaintPhaseCenter As AreaInfo

    Public scaleForDrawX As Double = 1.0
    Public scaleForDrawY As Double = 1.0

    Public cutBmpPhase1 As Bitmap
    Public cutBmpPhase2 As Bitmap
    Public cutBmpPhase3 As Bitmap
    Public cutBmpPhase4 As Bitmap
    Public cutBmpPhaseCenter As Bitmap

    Public bCheckSampleFile As Boolean = False

    Public tempbmp As Bitmap
    Public tempbmpcut As Bitmap

    Public frameBrush As SolidBrush = New SolidBrush(Color.FromArgb(70, Color.Red))

    Public enableFlag As Boolean = False

    Public specValue As SpecInfo

    Public calType As Integer = 1

    Public corp As AForge.Imaging.Filters.Crop

    Public filter As AForge.Imaging.Filters.Grayscale

    '解像力検査用グレースケール画像データ
    Public byteResPic(,) As Byte

    '解像力検査用グレースケール画像データ
    Public byteNewPic(,) As Byte


    '画面再描画用、オリジナル画像
    Public bmpBaseData As Bitmap
    'argb型のベース画像データ
    Public argbBaseData(,) As ArgbData

    Public Structure AreaInfo
        Dim StartPoint As Point
        Dim AreaSize As Size
    End Structure

    Private Sub checkGateStatus()
        Dim lRtn As Long = 0

        Dim requestKey As Long = 0
        Dim reponse As Long = 0

        Dim errorCode As Long = 0

        Dim readBuffer(10) As Byte


        lRtn = Smart2000.Net.App.Smart2000App.Smart2000Open(gateID(0), &H93110DF9, &H8880B602, &H6C5681B0, &H2D176276, requestKey)

        If lRtn <> 0 Then
            gateStatus = &HFF
            Smart2000.Net.App.Smart2000App.Smart2000Close(gateID(0))
            Exit Sub
        End If

        lRtn = Smart2000.Net.App.Smart2000App.Smart2000Verify(gateID(0), requestKey)
        If lRtn <> 0 Then
            gateStatus = &HFF
            Smart2000.Net.App.Smart2000App.Smart2000Close(gateID(0))
            Exit Sub
        End If

        lRtn = Smart2000.Net.App.Smart2000App.Smart2000ReadFileStorage(gateID(0), 0, readBuffer)
        If lRtn <> 0 Then
            errorCode = Smart2000.Net.App.Smart2000App.Smart2000GetLastError()
            gateStatus = &HFF
            Smart2000.Net.App.Smart2000App.Smart2000Close(gateID(0))
            Exit Sub
        End If

        Dim readString As String = ""
        For i As Integer = 0 To UBound(readBuffer)
            readString = readString & Chr(readBuffer(i))
        Next

        Try
            gateStatus = CInt(readString)
        Catch ex As Exception
            gateStatus = &HFF
        End Try
        Smart2000.Net.App.Smart2000App.Smart2000Close(gateID(0))
    End Sub

    Public Structure SpecInfo
        Dim specValuePhase1 As Integer
        Dim specValuePhase2 As Integer
        Dim specValuePhase3 As Integer
        Dim specValuePhase4 As Integer
        Dim specValuePhaseCenter As Integer
        Dim specValueGain As Integer
    End Structure

    Public Structure ArgbData
        Dim B As Byte
        Dim G As Byte
        Dim R As Byte
        Dim A As Byte
    End Structure


    Public Function findGate() As Boolean
        Dim lRtn As Long

        findGate = False
        lRtn = Smart2000.Net.App.Smart2000App.Smart2000Find("Definition evaluation", gateID, gateCount)

        If lRtn = 0 Then
            findGate = True
        Else
            gateCount = 0
            gateID(0) = 0
            gateID(1) = 0
            gateID(2) = 0
            gateID(3) = 0

        End If

    End Function
    Public Function saveSampleImage() As Boolean

        saveSampleImage = False

        Try
            If picboxMain.Image Is Nothing Then
                MsgBox("摄像头采集图像失败，无法生成样本图片")
                Exit Function
            Else
                If File.Exists("sample.jpg") Then
                    File.Delete("sample.jpg")
                End If

                picboxMain.Image.Save("sample.jpg")

            End If
        Catch ex As Exception
            MsgBox("生成摄像头样本图片失败")
            Exit Function
        End Try

        saveSampleImage = True

    End Function

    Private Sub frmMain_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
        Dim sampleBMP As Bitmap

        If Not bCheckSampleFile Then
            bCheckSampleFile = True

            If Not File.Exists("sample.jpg") Then
                MsgBox("没有发现摄像头样本图片，请先执行一次【单步验算】")
            Else

                sampleBMP = New Bitmap("sample.jpg")

                scaleForDrawX = picboxMain.Width / sampleBMP.Width
                scaleForDrawY = picboxMain.Height / sampleBMP.Height

                sampleBMP.Dispose()

                syncAreaInfo()

            End If
        End If
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim bGateStatus As Boolean

        bGateStatus = findGate()

        If Not bGateStatus Then
            MsgBox("未检索到加密锁，请先插入加密锁再打开程序")
            End
            If gateCount > 1 Then
                MsgBox("检索到超过1个加密锁，请移除多余的加密锁再启动程序")
                End

            End If
        End If

        'TimGate.Start()

        CaptureFrame = New Bitmap(picboxMain.Width, picboxMain.Height)
        'gCheckFrame = picboxMain.CreateGraphics
        gCheckFrame = pb1.CreateGraphics

        pb1.Parent = picboxMain
        pb1.BackColor = Color.Transparent

        ReadAreaInfo()
        fillAreaParam()


        ReadSpecInfo()
        fillSpecValue()

        GetDeviceList()

        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedSingle

    End Sub

    Private Sub Form1_UnLoad(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.FormClosing
        Timer1.Stop()
        gCheckFrame.Dispose()

        Timer1.Enabled = False
        If Not (videoSource Is Nothing) Then
            If videoSource.IsRunning Then
                videoSource.SignalToStop()
            End If
        End If

    End Sub

    Public Sub syncAreaInfo()
        areaForPaintPhase1.StartPoint = changePointScale(areaPhase1.StartPoint, 1)
        areaForPaintPhase1.AreaSize = changeSizeScale(areaPhase1.AreaSize, 1)

        areaForPaintPhase2.StartPoint = changePointScale(areaPhase2.StartPoint, 1)
        areaForPaintPhase2.AreaSize = changeSizeScale(areaPhase2.AreaSize, 1)

        areaForPaintPhase3.StartPoint = changePointScale(areaPhase3.StartPoint, 1)
        areaForPaintPhase3.AreaSize = changeSizeScale(areaPhase3.AreaSize, 1)

        areaForPaintPhase4.StartPoint = changePointScale(areaPhase4.StartPoint, 1)
        areaForPaintPhase4.AreaSize = changeSizeScale(areaPhase4.AreaSize, 1)

        areaForPaintPhaseCenter.StartPoint = changePointScale(areaPhaseCenter.StartPoint, 1)
        areaForPaintPhaseCenter.AreaSize = changeSizeScale(areaPhaseCenter.AreaSize, 1)


    End Sub

    'Byte型グレー画像を１次微分（グラディエント）で輪郭抽出（Byte型の別配列で返す）
    Public Function GradientForByte(ByRef bytePicData(,) As Byte, _
                                        ByRef byteBinPicData(,) As Byte, _
                                        Optional ByVal dGain As Double = 1.0, _
                                        Optional ByVal iOpType As Integer = 0) As Boolean
        Dim iCount As Integer
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataSizeX As Integer
        Dim iDataSizeY As Integer

        Dim iPicData(8) As Integer
        Dim dXX As Double
        Dim dYY As Double
        Dim dZZ As Double


        'オペレーターの係数：
        Dim iCX(8) As Integer
        Dim iCY(8) As Integer

        'オペレーターの係数：通常の差分
        Dim iCXN() As Integer = {0, 0, 0, _
                                0, 1, -1, _
                                0, 0, 0}
        Dim iCYN() As Integer = {0, 0, 0, _
                                0, 1, 0, _
                                0, -1, 0}

        'オペレーターの係数：Roberts
        Dim iCXR() As Integer = {0, 0, 0, _
                                0, 1, 0, _
                                0, 0, -1}
        Dim iCYR() As Integer = {0, 0, 0, _
                                0, 0, 1, _
                                0, -1, 0}

        'オペレーターの係数：Sobel
        Dim iCXS() As Integer = {-1, 0, 1, _
                                -2, 0, 2, _
                                -1, 0, 1}
        Dim iCYS() As Integer = {-1, -2, -1, _
                                0, 0, 0, _
                                1, 2, 1}
        GradientForByte = False

        Select Case iOpType
            Case 0
                For iCount = 0 To 8
                    iCX(iCount) = iCXN(iCount)
                    iCY(iCount) = iCYN(iCount)
                Next
            Case 1
                For iCount = 0 To 8
                    iCX(iCount) = iCXR(iCount)
                    iCY(iCount) = iCYR(iCount)
                Next
            Case 2
                For iCount = 0 To 8
                    iCX(iCount) = iCXS(iCount)
                    iCY(iCount) = iCYS(iCount)
                Next
        End Select

        Try
            'RGB2次元配列のサイズを取得
            iDataSizeX = UBound(bytePicData, 1)
            iDataSizeY = UBound(bytePicData, 2)
            ReDim byteBinPicData(iDataSizeX, iDataSizeY)

            For iPosY = 1 To iDataSizeY - 1
                For iPosX = 1 To iDataSizeX - 1
                    'Application.DoEvents()
                    iPicData(0) = bytePicData(iPosX - 1, iPosY - 1)
                    iPicData(1) = bytePicData(iPosX - 1, iPosY)
                    iPicData(2) = bytePicData(iPosX - 1, iPosY + 1)
                    iPicData(3) = bytePicData(iPosX, iPosY - 1)
                    iPicData(4) = bytePicData(iPosX, iPosY)
                    iPicData(5) = bytePicData(iPosX, iPosY + 1)
                    iPicData(6) = bytePicData(iPosX + 1, iPosY - 1)
                    iPicData(7) = bytePicData(iPosX + 1, iPosY)
                    iPicData(8) = bytePicData(iPosX + 1, iPosY + 1)
                    dXX = 0
                    dYY = 0
                    For iCount = 0 To 8
                        dXX += CDbl(iCX(iCount) * iPicData(iCount))
                        dYY += CDbl(iCY(iCount) * iPicData(iCount))
                    Next
                    dZZ = dGain * Math.Sqrt(dXX * dXX + dYY * dYY)
                    byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                Next
            Next

            GradientForByte = True

        Catch ex As Exception
            MsgBox("清晰度评价函数运算出错" & _
                    ControlChars.CrLf & ex.Message, , "GradientForByte")
        End Try
    End Function

    Public Function changePointScale(ByVal inputPoint As Point, Optional ByVal changeType As Integer = 0) As Point
        changePointScale = inputPoint


        If changeType = 0 Then
            '控件坐标系→原始画像坐标系
            changePointScale.X = inputPoint.X * (1 / scaleForDrawX)
            changePointScale.Y = inputPoint.Y * (1 / scaleForDrawY)


        Else
            '原始画像坐标系→控件坐标系
            changePointScale.X = inputPoint.X * scaleForDrawX
            changePointScale.Y = inputPoint.Y * scaleForDrawY
        End If


    End Function

    Public Function changeSizeScale(ByVal inputSize As Size, Optional ByVal changeType As Integer = 0) As Size
        changeSizeScale = inputSize

        If changeType = 0 Then
            '控件坐标系→原始画像坐标系
            changeSizeScale.Width = inputSize.Width * (1 / scaleForDrawX)
            changeSizeScale.Height = inputSize.Height * (1 / scaleForDrawY)


        Else
            '原始画像坐标系→控件坐标系
            changeSizeScale.Width = inputSize.Width * scaleForDrawX
            changeSizeScale.Height = inputSize.Height * scaleForDrawY
        End If

    End Function


    'Double型グレー画像を2次微分（ラプラシアン）で輪郭抽出（Byte型の別配列で返す）
    Public Function LaplacianForDouble(ByRef dPicData(,) As Double, _
                            ByRef byteBinPicData(,) As Byte, _
                            Optional ByVal iScale As Integer = 1, _
                            Optional ByVal iAve As Integer = 200, _
                            Optional ByVal iOpType As Integer = 0) As Boolean
        Dim iCount As Integer
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataSizeX As Integer
        Dim iDataSizeY As Integer

        Dim dResult(,) As Double
        Dim dMax As Double
        Dim dMin As Double
        Dim dRange As Double
        Dim dPixData(8) As Double
        Dim dLL As Double
        Dim dZZ As Double
        Dim dGain As Double


        'オペレーターの係数：
        Dim iCL(8) As Integer

        'オペレーターの係数：ラプラシアン0
        Dim iCL0() As Integer = {-1, -1, -1, _
                                -1, 8, -1, _
                                -1, -1, -1}

        'オペレーターの係数：ラプラシアン1
        Dim iCL1() As Integer = {0, -1, 0, _
                                -1, 4, -1, _
                                0, -1, 0}

        'オペレーターの係数：ラプラシアン3
        Dim iCL2() As Integer = {1, -2, 1, _
                                -2, 4, -2, _
                                1, -2, 1}
        LaplacianForDouble = False

        Select Case iOpType
            Case 0
                For iCount = 0 To 8
                    iCL(iCount) = iCL0(iCount)
                Next
            Case 1
                For iCount = 0 To 8
                    iCL(iCount) = iCL1(iCount)
                Next
            Case 2
                For iCount = 0 To 8
                    iCL(iCount) = iCL2(iCount)
                Next
            Case Else
                For iCount = 0 To 8
                    iCL(iCount) = iCL0(iCount)
                Next
        End Select


        Try
            'RGB2次元配列のサイズを取得
            iDataSizeX = UBound(dPicData, 1)
            iDataSizeY = UBound(dPicData, 2)
            ReDim byteBinPicData(iDataSizeX, iDataSizeY)
            ReDim dResult(iDataSizeX, iDataSizeY)
            dMax = -255
            dMin = 255

            For iPosY = 0 To iDataSizeY
                For iPosX = 0 To iDataSizeX
                    iCount = 0

                    '左上
                    If iPosX - iScale >= 0 And iPosY - iScale >= 0 Then
                        dPixData(0) = dPicData(iPosX - iScale, iPosY - iScale)
                        iCount += -1 * iCL(0)
                    Else
                        dPixData(0) = 0
                    End If

                    '上
                    If iPosY - iScale >= 0 Then
                        dPixData(1) = dPicData(iPosX, iPosY - iScale)
                        iCount += -1 * iCL(1)
                    Else
                        dPixData(1) = 0
                    End If

                    '右上
                    If iPosX + iScale <= iDataSizeX And iPosY - iScale >= 0 Then
                        dPixData(2) = dPicData(iPosX + iScale, iPosY - iScale)
                        iCount += -1 * iCL(2)
                    Else
                        dPixData(2) = 0
                    End If

                    '左
                    If iPosX - iScale >= 0 Then
                        dPixData(3) = dPicData(iPosX - iScale, iPosY)
                        iCount += -1 * iCL(3)
                    Else
                        dPixData(3) = 0
                    End If

                    '中心
                    dPixData(4) = dPicData(iPosX, iPosY)

                    '右
                    If iPosX + iScale <= iDataSizeX Then
                        dPixData(5) = dPicData(iPosX + iScale, iPosY)
                        iCount += -1 * iCL(5)
                    Else
                        dPixData(5) = 0
                    End If

                    '左下
                    If iPosX - iScale >= 0 And iPosY + iScale <= iDataSizeY Then
                        dPixData(6) = dPicData(iPosX - iScale, iPosY + iScale)
                        iCount += -1 * iCL(6)
                    Else
                        dPixData(6) = 0
                    End If

                    '下
                    If iPosY + iScale <= iDataSizeY Then
                        dPixData(7) = dPicData(iPosX, iPosY + iScale)
                        iCount += -1 * iCL(7)
                    Else
                        dPixData(7) = 0
                    End If

                    '右下
                    If iPosX + iScale <= iDataSizeX And iPosY + iScale <= iDataSizeY Then
                        dPixData(8) = dPicData(iPosX + iScale, iPosY + iScale)
                        iCount += -1 * iCL(8)
                    Else
                        dPixData(8) = 0
                    End If

                    dLL = 0
                    dLL += CDbl(iCL(0)) * dPixData(0)
                    dLL += CDbl(iCL(1)) * dPixData(1)
                    dLL += CDbl(iCL(2)) * dPixData(2)
                    dLL += CDbl(iCL(3)) * dPixData(3)
                    dLL += CDbl(iCount) * dPixData(4)
                    dLL += CDbl(iCL(5)) * dPixData(5)
                    dLL += CDbl(iCL(6)) * dPixData(6)
                    dLL += CDbl(iCL(7)) * dPixData(7)
                    dLL += CDbl(iCL(8)) * dPixData(8)


                    dResult(iPosX, iPosY) = dLL
                    If dMax < dLL Then dMax = dLL
                    If dMin > dLL Then dMin = dLL
                Next
            Next


            '明るさを最大輝度が狙い輝度になるように最適化
            dRange = dMax - dMin
            dGain = CDbl(iAve) / dRange
            For iPosY = 0 To iDataSizeY
                For iPosX = 0 To iDataSizeX
                    dZZ = (dResult(iPosX, iPosY) - dMin) * dGain
                    byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                Next
            Next


            '周辺部分のシェーディングによる輝度差を補正
            Dim dRefAve As Double
            Dim dPixAve As Double
            '左上
            dRefAve = 0
            dPixAve = 0
            For iPosY = 0 To iScale - 1
                For iPosX = 0 To iScale - 1
                    dRefAve = dRefAve + CDbl(byteBinPicData(iPosX + iScale, iPosY + iScale))
                    dPixAve = dPixAve + CDbl(byteBinPicData(iPosX, iPosY))
                Next
            Next
            dRefAve = dRefAve / iScale / iScale
            dPixAve = dPixAve / iScale / iScale
            dGain = dRefAve / dPixAve
            For iPosY = 0 To iScale - 1
                For iPosX = 0 To iScale - 1
                    If byteBinPicData(iPosX, iPosY) = 0 Then
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dRefAve))
                    Else
                        dZZ = CDbl(byteBinPicData(iPosX, iPosY)) * dGain
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                    End If
                Next
            Next

            '右上
            dRefAve = 0
            dPixAve = 0
            For iPosY = 0 To iScale - 1
                For iPosX = iDataSizeX - iScale + 1 To iDataSizeX
                    dRefAve = dRefAve + CDbl(byteBinPicData(iPosX - iScale, iPosY + iScale))
                    dPixAve = dPixAve + CDbl(byteBinPicData(iPosX, iPosY))
                Next
            Next
            dRefAve = dRefAve / iScale / iScale
            dPixAve = dPixAve / iScale / iScale
            dGain = dRefAve / dPixAve
            For iPosY = 0 To iScale - 1
                For iPosX = iDataSizeX - iScale + 1 To iDataSizeX
                    If byteBinPicData(iPosX, iPosY) = 0 Then
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dRefAve))
                    Else
                        dZZ = CDbl(byteBinPicData(iPosX, iPosY)) * dGain
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                    End If
                Next
            Next

            '左下
            dRefAve = 0
            dPixAve = 0
            For iPosY = iDataSizeY - iScale + 1 To iDataSizeY
                For iPosX = 0 To iScale - 1
                    dRefAve = dRefAve + CDbl(byteBinPicData(iPosX + iScale, iPosY - iScale))
                    dPixAve = dPixAve + CDbl(byteBinPicData(iPosX, iPosY))
                Next
            Next
            dRefAve = dRefAve / iScale / iScale
            dPixAve = dPixAve / iScale / iScale
            dGain = dRefAve / dPixAve
            For iPosY = iDataSizeY - iScale + 1 To iDataSizeY
                For iPosX = 0 To iScale - 1
                    If byteBinPicData(iPosX, iPosY) = 0 Then
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dRefAve))
                    Else
                        dZZ = CDbl(byteBinPicData(iPosX, iPosY)) * dGain
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                    End If
                Next
            Next

            '右下
            dRefAve = 0
            dPixAve = 0
            For iPosY = iDataSizeY - iScale + 1 To iDataSizeY
                For iPosX = iDataSizeX - iScale + 1 To iDataSizeX
                    dRefAve = dRefAve + CDbl(byteBinPicData(iPosX - iScale, iPosY - iScale))
                    dPixAve = dPixAve + CDbl(byteBinPicData(iPosX, iPosY))
                Next
            Next
            dRefAve = dRefAve / iScale / iScale
            dPixAve = dPixAve / iScale / iScale
            dGain = dRefAve / dPixAve
            For iPosY = iDataSizeY - iScale + 1 To iDataSizeY
                For iPosX = iDataSizeX - iScale + 1 To iDataSizeX
                    If byteBinPicData(iPosX, iPosY) = 0 Then
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dRefAve))
                    Else
                        dZZ = CDbl(byteBinPicData(iPosX, iPosY)) * dGain
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                    End If
                Next
            Next


            '上
            For iPosX = iScale To iDataSizeX - iScale
                dRefAve = (CDbl(byteBinPicData(iPosX, iScale)) + _
                            CDbl(byteBinPicData(iPosX, iScale + 1)) + _
                            CDbl(byteBinPicData(iPosX, iScale + 2)) + _
                            CDbl(byteBinPicData(iPosX, iScale + 3))) / 4.0#
                dPixAve = 0
                For iPosY = 0 To iScale - 1
                    dPixAve = dPixAve + CDbl(byteBinPicData(iPosX, iPosY))
                Next
                dPixAve = dPixAve / iScale
                dGain = dRefAve / dPixAve
                For iPosY = 0 To iScale - 1
                    If byteBinPicData(iPosX, iPosY) = 0 Then
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dRefAve))
                    Else
                        dZZ = CDbl(byteBinPicData(iPosX, iPosY)) * dGain
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                    End If
                Next
            Next

            '下
            For iPosX = iScale To iDataSizeX - iScale
                dRefAve = (CDbl(byteBinPicData(iPosX, iDataSizeY - iScale)) + _
                            CDbl(byteBinPicData(iPosX, iDataSizeY - iScale - 1)) + _
                            CDbl(byteBinPicData(iPosX, iDataSizeY - iScale - 2)) + _
                            CDbl(byteBinPicData(iPosX, iDataSizeY - iScale - 3))) / 4.0#
                dPixAve = 0
                For iPosY = iDataSizeY - iScale + 1 To iDataSizeY
                    dPixAve = dPixAve + CDbl(byteBinPicData(iPosX, iPosY))
                Next
                dPixAve = dPixAve / iScale
                dGain = dRefAve / dPixAve
                For iPosY = iDataSizeY - iScale + 1 To iDataSizeY
                    If byteBinPicData(iPosX, iPosY) = 0 Then
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dRefAve))
                    Else
                        dZZ = CDbl(byteBinPicData(iPosX, iPosY)) * dGain
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                    End If
                Next
            Next

            '左
            For iPosY = iScale To iDataSizeY - iScale
                dRefAve = (CDbl(byteBinPicData(iScale, iPosY)) + _
                            CDbl(byteBinPicData(iScale + 1, iPosY)) + _
                            CDbl(byteBinPicData(iScale + 2, iPosY)) + _
                            CDbl(byteBinPicData(iScale + 3, iPosY))) / 4.0#
                dPixAve = 0
                For iPosX = 0 To iScale - 1
                    dPixAve = dPixAve + CDbl(byteBinPicData(iPosX, iPosY))
                Next
                dPixAve = dPixAve / iScale
                dGain = dRefAve / dPixAve
                For iPosX = 0 To iScale - 1
                    If byteBinPicData(iPosX, iPosY) = 0 Then
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dRefAve))
                    Else
                        dZZ = CDbl(byteBinPicData(iPosX, iPosY)) * dGain
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                    End If
                Next
            Next

            '右
            For iPosY = iScale To iDataSizeY - iScale
                dRefAve = (CDbl(byteBinPicData(iDataSizeX - iScale, iPosY)) + _
                            CDbl(byteBinPicData(iDataSizeX - iScale - 1, iPosY)) + _
                            CDbl(byteBinPicData(iDataSizeX - iScale - 2, iPosY)) + _
                            CDbl(byteBinPicData(iDataSizeX - iScale - 3, iPosY))) / 4.0#
                dPixAve = 0
                For iPosX = iDataSizeX - iScale + 1 To iDataSizeX
                    dPixAve = dPixAve + CDbl(byteBinPicData(iPosX, iPosY))
                Next
                dPixAve = dPixAve / iScale
                dGain = dRefAve / dPixAve
                For iPosX = iDataSizeX - iScale + 1 To iDataSizeX
                    If byteBinPicData(iPosX, iPosY) = 0 Then
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dRefAve))
                    Else
                        dZZ = CDbl(byteBinPicData(iPosX, iPosY)) * dGain
                        byteBinPicData(iPosX, iPosY) = RGBRange(CInt(dZZ))
                    End If
                Next
            Next

            LaplacianForDouble = True

        Catch ex As Exception
            MsgBox("二次微分算法出错" & _
                    ControlChars.CrLf & ex.Message, , "LaplacianForDouble")
        End Try
    End Function


    'RGBRange
    '値を0～255の範囲になるように調節します。
    '調節前の値を指定します。
    '調節後の値を返します。この値は必ず0～255の範囲内です。
    Private Function RGBRange(ByVal iData As Integer) As Byte
        Select Case iData
            Case Is < 0
                Return 0
            Case Is > 255
                Return 255
            Case Else
                Return CByte(iData)
        End Select
    End Function


    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
        Dim bRtn As Boolean = False

        initBrush()

        bRtn = checkValue()

        If Not bRtn Then
            Exit Sub
        End If

        If (videoSource Is Nothing) Then
            MsgBox("摄像头未启动")
        Else
            If videoSource.IsRunning Then
                btnStart.Enabled = False
                Button1.Enabled = True
                btnEndCal.Enabled = True

                checkGateStatus()

                Timer1.Start()
                TimGate.Start()
            Else
                MsgBox("摄像头未处于运行状态")
            End If
        End If
    End Sub

    Public Function checkValue() As Boolean
        checkValue = False

        If Not IsNumeric(txtBoxSpec1.Text & txtBoxSpec2.Text & txtBoxSpec3.Text & txtBoxSpec4.Text & txtBoxSpecCenter.Text) Then
            MsgBox("规格值中有非数字成分，请确认。")
            Exit Function
        End If

        If Not IsNumeric(txtResultGain.Text) Then
            MsgBox("Gain值中有非数字成分，请确认。")
            Exit Function
        End If

        checkValue = True

    End Function

    Public Sub startCal()
        enableFlag = False
        'DoEvents()

        If picboxMain.Image Is Nothing Then
            Timer1.Stop()
            MsgBox("没有加载有效图像，请确认摄像头是否正常输出图像")
            Exit Sub
        End If

        Try
            tempbmp = filter.Apply(picboxMain.Image.Clone)
        Catch ex As Exception
            TextBox1.AppendText(ex.Message.ToString)
        End Try





        If chkBoxEnablePhase1.Checked Then

            CutPicture(areaPhase1.StartPoint, areaPhase1.AreaSize, tempbmp, tempbmpcut)

            txtCurrentResultPhase1.Text = CalcAFValue(tempbmpcut, CInt(txtResultGain.Text)).ToString
            txtCurrentResultPhase1.Refresh()

            If CInt(txtCurrentResultPhase1.Text) >= CInt(txtBoxSpec1.Text) Then
                txtCurrentResultPhase1.BackColor = Color.Green
            Else
                txtCurrentResultPhase1.BackColor = Color.Red
            End If

            If chkBoxDrawResult.Checked Then
                picBoxPhase1.Image = tempbmpcut.Clone
            End If
        End If

        ' Application.DoEvents()

        If chkBoxEnablePhase2.Checked Then

            CutPicture(areaPhase2.StartPoint, areaPhase2.AreaSize, tempbmp, tempbmpcut)

            txtCurrentResultPhase2.Text = CalcAFValue(tempbmpcut, CInt(txtResultGain.Text)).ToString
            txtCurrentResultPhase2.Refresh()

            If CInt(txtCurrentResultPhase2.Text) >= CInt(txtBoxSpec2.Text) Then
                txtCurrentResultPhase2.BackColor = Color.Green
            Else
                txtCurrentResultPhase2.BackColor = Color.Red
            End If

            If chkBoxDrawResult.Checked Then
                picBoxPhase2.Image = tempbmpcut.Clone
            End If
        End If

        'Application.DoEvents()

        If chkBoxEnablePhase3.Checked Then

            CutPicture(areaPhase3.StartPoint, areaPhase3.AreaSize, tempbmp, tempbmpcut)

            txtCurrentResultPhase3.Text = CalcAFValue(tempbmpcut, CInt(txtResultGain.Text)).ToString
            txtCurrentResultPhase3.Refresh()

            If CInt(txtCurrentResultPhase3.Text) >= CInt(txtBoxSpec3.Text) Then
                txtCurrentResultPhase3.BackColor = Color.Green
            Else
                txtCurrentResultPhase3.BackColor = Color.Red
            End If

            If chkBoxDrawResult.Checked Then
                picBoxPhase3.Image = tempbmpcut.Clone
            End If
        End If

        'Application.DoEvents()

        If chkBoxEnablePhase4.Checked Then

            CutPicture(areaPhase4.StartPoint, areaPhase4.AreaSize, tempbmp, tempbmpcut)

            txtCurrentResultPhase4.Text = CalcAFValue(tempbmpcut, CInt(txtResultGain.Text)).ToString
            txtCurrentResultPhase4.Refresh()

            If CInt(txtCurrentResultPhase4.Text) >= CInt(txtBoxSpec4.Text) Then
                txtCurrentResultPhase4.BackColor = Color.Green
            Else
                txtCurrentResultPhase4.BackColor = Color.Red
            End If

            If chkBoxDrawResult.Checked Then
                picBoxPhase4.Image = tempbmpcut.Clone
            End If
        End If

        'Application.DoEvents()

        If chkBoxEnablePhaseCenter.Checked Then

            CutPicture(areaPhaseCenter.StartPoint, areaPhaseCenter.AreaSize, tempbmp, tempbmpcut)

            txtCurrentResultPhaseCenter.Text = CalcAFValue(tempbmpcut, CInt(txtResultGain.Text)).ToString
            txtCurrentResultPhaseCenter.Refresh()

            If CInt(txtCurrentResultPhaseCenter.Text) >= CInt(txtBoxSpecCenter.Text) Then
                txtCurrentResultPhaseCenter.BackColor = Color.Green
            Else
                txtCurrentResultPhaseCenter.BackColor = Color.Red
            End If

            If chkBoxDrawResult.Checked Then
                picBoxPhaseCenter.Image = tempbmpcut.Clone
            End If
        End If

        enableFlag = True


    End Sub

    Public Function CalcAFValue(ByVal scrBmp As Bitmap, Optional ByVal gain As Integer = 1) As Long
        Dim sum As Long = 0

        Dim x As Integer
        Dim y As Integer
        Dim xEnd As Integer
        Dim yEnd As Integer


        CalcAFValue = 0

        If gateStatus <> 221177 Then
            CalcAFValue = Math.Round(Now.Millisecond) * 100
            labError.Visible = True
            TimEnd.Start()
            Exit Function
        End If

        'picBoxPhase2.Image = tempbmp

        'iPicWidth = tempbmp.Width
        'iPicHeight = tempbmp.Height



        BitmapToByte(scrBmp, byteResPic)

        If radRobert.Checked Then
            calType = 1
        End If

        If radSobel.Checked Then
            calType = 2
        End If

        If radHardSobel1.Checked Then
            calType = 3
        End If

        If radHardSobel2.Checked Then
            calType = 4
        End If

        If radHardSobel3.Checked Then
            calType = 5
        End If

        Select Case calType
            Case 1
                Roberts(byteResPic, byteNewPic)
            Case 2
                SobelCal(byteResPic, byteNewPic)
            Case 3
                GradientForByte(byteResPic, byteNewPic)
            Case 4
                GradientForByte(byteResPic, byteNewPic, 1.0, 1)
            Case 5
                GradientForByte(byteResPic, byteNewPic, 1.0, 2)
            Case Else
                MsgBox("算法选择错误")
                Exit Function
        End Select

        '
        '


        'Application.DoEvents()

        xEnd = UBound(byteNewPic, 1)
        yEnd = UBound(byteNewPic, 2)

        For x = 3 To xEnd - 3
            For y = 3 To yEnd - 3
                sum = sum + byteNewPic(x, y)
            Next
        Next

        If gain <> 0 Then
            CalcAFValue = sum / gain
        End If

    End Function

    Public Function CutPicture(ByVal StartPoint As Point, ByVal cutSize As Size, ByRef scrBmp As Bitmap, ByRef ResultBmp As Bitmap) As Boolean
        CutPicture = False

        'Try
        '    Dim cloneRect As New Rectangle(StartPoint, cutSize)
        '    Dim format As Imaging.PixelFormat = scrBmp.PixelFormat
        '    ResultBmp = scrBmp.Clone(cloneRect, format)
        '    CutPicture = True

        'Catch ex As Exception
        '    MsgBox(ex.ToString & ControlChars.CrLf & ControlChars.CrLf & _
        '             "CutPicture Error", , "CutPicture")
        'End Try

        Try
            corp = New AForge.Imaging.Filters.Crop(New Rectangle(StartPoint, cutSize))
            ResultBmp = corp.Apply(scrBmp)
        Catch ex As Exception
            MsgBox(ex.ToString & ControlChars.CrLf & ControlChars.CrLf & _
                         "CutPicture Error", , "CutPicture")
        End Try



    End Function

    Public Function BitmapToByte(ByRef bmpPicData As Bitmap, _
                                ByRef bytePicData(,) As Byte) As Boolean
        'BitmapデータをRGB配列にコピー
        '元画像は8bitグレースケールBitmap→8bitグレースケールデータ用)
        Dim iOfset As Integer
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iBmpWidth As Integer
        Dim iBmpHeight As Integer
        Dim ByteRgbValues() As Byte
        Dim pfBitmap As PixelFormat = bmpPicData.PixelFormat

        BitmapToByte = False

        Try
            pfBitmap = bmpPicData.PixelFormat
            If pfBitmap <> PixelFormat.Format8bppIndexed Then
                MsgBox("Bitmap文件转换出错（颜色深度不匹配）")
                Exit Function
            End If

            iBmpWidth = bmpPicData.Width
            iBmpHeight = bmpPicData.Height

            'Bitmapの矩形サイズ定義
            Dim rectBmp As New Rectangle(0, 0, iBmpWidth, iBmpHeight)

            'BitmapをBitmapDataに定義・コピーに備えてLockする  
            Dim bmpData As Imaging.BitmapData = bmpPicData.LockBits(rectBmp, _
                Imaging.ImageLockMode.ReadWrite, bmpPicData.PixelFormat)

            'BitmapDataのポインタを取得
            Dim ptrBmpData As IntPtr = bmpData.Scan0

            'Bitmapの横幅データサイズ×Bitmapの高さ＝全体のデータサイズ
            Dim iBytes As Integer = bmpData.Stride * iBmpHeight

            'BitmapDataをコピーされる作業用1次元配列のサイズを定義
            ReDim ByteRgbValues(iBytes - 1)

            'Bitmapの1ピクセルあたりのデータサイズを計算
            Dim iBytePerPixel As Integer = CInt(bmpData.Stride / iBmpWidth)

            'BitmapDataを作業用1次元配列にコピーする
            Marshal.Copy(ptrBmpData, ByteRgbValues, 0, iBytes)

            'BitmapDataを Unlock
            bmpPicData.UnlockBits(bmpData)

            '戻り値のRGB配列の大きさをBitmapデータに合わせて変更
            ReDim bytePicData(bmpPicData.Width - 1, bmpPicData.Height - 1)

            '作業用1次元配列からARGB2次元配列にコピー
            'コピー先のαチャンネルは試用しないので無視、RGBのみコピー
            For iPosY = 0 To iBmpHeight - 1
                For iPosX = 0 To iBmpWidth - 1
                    'カラー画像
                    iOfset = (iPosX + (iPosY * iBmpWidth)) * iBytePerPixel
                    bytePicData(iPosX, iPosY) = ByteRgbValues(iOfset)
                Next
            Next
            BitmapToByte = True

        Catch ex As Exception
            MsgBox(ex.ToString & ControlChars.CrLf & ControlChars.CrLf & _
                     "Bitmap转换函数错误", , "BitmapToByte")
        End Try

        Erase ByteRgbValues
    End Function


    '//////////////////////////////////////////////////
    '//     画像ローダー
    '//         （JPEG,BMP,TIFF,RAW対応)
    '//             by Hidemi Otaki
    '//////////////////////////////////////////////////
    Public Function LoadPicData(ByVal sPicFilePath As String, _
                                    ByRef bmpPicData As Bitmap, _
                                    ByRef argbPicData(,) As ArgbData, _
                                    ByRef iPicWidth As Integer, _
                                    ByRef iPicHeight As Integer) As Boolean
        Dim bRtn As Boolean

        '戻り値をクリア
        LoadPicData = False

        'RAWデータの展開は別関数で処理
        If Not (Microsoft.VisualBasic.Strings.Right(sPicFilePath, 3) = "RAW" Or Microsoft.VisualBasic.Strings.Right(sPicFilePath, 3) = "raw") Then
            Try


                '画像ファイルからのBitmapデータを取得
                '2008/09/01 大瀧 画像をFileSystemObjectを用いて開くように修正

                'Dim fs As System.IO.FileStream
                'fs = New System.IO.FileStream(sPicFilePath, _
                '                                IO.FileMode.Open, _
                '                                IO.FileAccess.Read)
                'bmpPicData = CType(System.Drawing.Image.FromStream(fs), Bitmap)
                'fs.Close()

                '2008/09/01 大瀧 ビットマップに直接展開するとファイルを握られたままになり、他のソフトで操作できなくなってしまう
                'bmpPicData = New Bitmap(sPicFilePath, True)

                '画像ファイルの幅及び高さを取得する
                'bRtn = GetPicFileSize(sPicFilePath, iPicWidth, iPicHeight)

                iPicWidth = tempbmp.Width
                iPicHeight = tempbmp.Height

                'If Not bRtn Then
                '    Exit Function
                'End If

                '画像用RGB配列にBitmapデータをコピー
                'bRtn = BitmapToArgb(bmpPicData, argbPicData)
                bRtn = BitmapToArgb(tempbmp, argbPicData)
                If Not bRtn Then
                    Exit Function
                End If

            Catch ex As ArgumentException
                MsgBox(sPicFilePath & ControlChars.CrLf & _
                                "指定的文件无法加载或打开。")
                Exit Function
            End Try
        Else
            'RAWデータの展開は独自処理
            bRtn = LoadRawData(sPicFilePath, bmpPicData, argbPicData, iPicWidth, iPicHeight)
            If Not bRtn Then
                Exit Function
            End If
        End If

        LoadPicData = True
    End Function

    '///////////////////////////////////////////////////////////
    '//  黒しみテスターのDLLがはき出すRAW画像データの取得関数
    '///////////////////////////////////////////////////////////
    Public Function LoadRawData(ByVal sPicFilePath As String, _
                                ByRef bmpPicData As Bitmap, _
                                ByRef argbPicData(,) As ArgbData, _
                                ByVal iPicWidth As Integer, _
                                ByVal iPicHeight As Integer) As Boolean
        Dim byteRawData() As Byte
        Dim byteRgbData() As Byte
        Dim bmpdataPicData As Imaging.BitmapData
        Dim ipBmpPicData As IntPtr

        Dim iRtn As Integer
        Dim iAddX As Integer
        Dim iAddY As Integer
        Dim iBytes As Integer
        Dim iPicDataBytes As Integer
        Dim iOfset As Integer
        Dim iRgbOfset As Integer

        LoadRawData = False

        If File.Exists(sPicFilePath) Then
            Dim fiPicFile As New FileInfo(sPicFilePath)
            ReDim argbPicData(iPicWidth - 1, iPicHeight - 1)
            ReDim byteRgbData((iPicWidth * iPicHeight) * 3 - 1)
            Dim binReader As New BinaryReader(File.Open(sPicFilePath, FileMode.Open))

            Try
                iBytes = CInt(fiPicFile.Length)
                ReDim byteRawData(iBytes)
                iRtn = binReader.Read(byteRawData, 0, iBytes)

                '2009/11/30  大瀧    RAWデータ展開関数関係見直し
                '                    指定画像サイズとファイルサイズが異なる場合エラー
                '                    ちょうどファイルサイズが2倍の場合は16bit/PixelのRAW画像として扱う
                If iBytes = iPicWidth * iPicHeight Then
                    iPicDataBytes = iBytes
                    For iAddY = 0 To iPicHeight - 1
                        For iAddX = 0 To iPicWidth - 1
                            iOfset = (iAddX + iAddY * iPicWidth)
                            iRgbOfset = iOfset * 3
                            argbPicData(iAddX, iAddY).B = byteRawData(iOfset)
                            argbPicData(iAddX, iAddY).G = byteRawData(iOfset)
                            argbPicData(iAddX, iAddY).R = byteRawData(iOfset)
                            argbPicData(iAddX, iAddY).A = 0
                            byteRgbData(iRgbOfset) = byteRawData(iOfset)
                            byteRgbData(iRgbOfset + 1) = byteRawData(iOfset)
                            byteRgbData(iRgbOfset + 2) = byteRawData(iOfset)
                        Next
                    Next
                ElseIf iBytes = (iPicWidth * iPicHeight) * 2 Then
                    iPicDataBytes = CInt(CDbl(iBytes) / 2.0)
                    For iAddY = 0 To iPicHeight - 1
                        For iAddX = 0 To iPicWidth - 1
                            Dim iTempData As Integer
                            Dim byteTempData As Byte
                            iOfset = (iAddX * 2 + iAddY * iPicWidth * 2)
                            iTempData = CInt(byteRawData(iOfset + 1)) * &HFF + CInt(byteRawData(iOfset))
                            byteTempData = CByte(CDbl(iTempData) / CDbl(&H100))
                            iRgbOfset = (iAddX + iAddY * iPicWidth) * 3
                            argbPicData(iAddX, iAddY).B = byteTempData
                            argbPicData(iAddX, iAddY).G = byteTempData
                            argbPicData(iAddX, iAddY).R = byteTempData
                            argbPicData(iAddX, iAddY).A = 0
                            byteRgbData(iRgbOfset) = byteTempData
                            byteRgbData(iRgbOfset + 1) = byteTempData
                            byteRgbData(iRgbOfset + 2) = byteTempData
                        Next
                    Next
                Else
                    MsgBox("FilePath = " & sPicFilePath & ControlChars.CrLf & _
                            "上述文件无法处理")
                    binReader.Close()
                    Erase byteRawData
                    Erase byteRgbData
                    Exit Function
                End If

                'Bitmapオブジェクトをサイズ・フォーマットを指定して作成
                bmpPicData = New Bitmap(iPicWidth, iPicHeight, Drawing.Imaging.PixelFormat.Format24bppRgb)     'Color24bit/ピクセル 

                'Bitmapの矩形サイズ定義
                'BitmapをBitmapDataに定義・コピーに備えてLockする  
                bmpdataPicData = bmpPicData.LockBits(New Rectangle(0, 0, bmpPicData.Width, bmpPicData.Height), Imaging.ImageLockMode.ReadWrite, bmpPicData.PixelFormat)

                'BitmapDataのポインタを取得
                ipBmpPicData = bmpdataPicData.Scan0

                '配列から一気にBitmapDataに書き戻す
                Marshal.Copy(byteRgbData, 0, ipBmpPicData, iPicDataBytes * 3)

                'BitmapDataを Unlock
                bmpPicData.UnlockBits(bmpdataPicData)

                LoadRawData = True

            Catch ex As Exception
                MsgBox(ex.ToString & ControlChars.CrLf & _
                        "FilePath = " & sPicFilePath & ControlChars.CrLf & _
                        "指定文件不存在")
            End Try

            binReader.Close()
            Erase byteRawData
            Erase byteRgbData
        End If
    End Function

    '画像ファイルの幅及び高さを取得する
    Public Function GetPicFileSize(ByVal sPicFilePath As String, _
                                ByRef iPicWidth As Integer, _
                                ByRef iPicHeight As Integer) As Boolean
        Dim fs As System.IO.FileStream
        GetPicFileSize = False
        Try
            fs = New System.IO.FileStream(sPicFilePath, _
                                System.IO.FileMode.Open, System.IO.FileAccess.Read)
            iPicWidth = Image.FromStream(fs).Width
            iPicHeight = Image.FromStream(fs).Height
            fs.Close()
            GetPicFileSize = True
        Catch ex As Exception
            MsgBox(ex.ToString & ControlChars.CrLf & ControlChars.CrLf & _
                     "图像文件尺寸取得失败。", , "GetPicSize")
        End Try
    End Function

    '//////////////////////////////////////////////////////
    '// BitmapToArgb - BitmapオブジェクトをArgb型カラー画像データに変換
    '//             by Hidemi Otaki
    '//////////////////////////////////////////////////////
    Public Function BitmapToArgb(ByRef bmpPicData As Bitmap, _
                                ByRef argbPicData(,) As ArgbData) As Boolean
        'BitmapデータをRGB配列にコピー
        '元画像は24bitカラーor32bitカラーBitmap→32bitカラーARGBデータ用)
        Dim iOfset As Integer
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iBmpWidth As Integer
        Dim iBmpHeight As Integer
        Dim ByteRgbValues() As Byte
        Dim pfBitmap As PixelFormat = bmpPicData.PixelFormat

        BitmapToArgb = False

        Try
            pfBitmap = bmpPicData.PixelFormat
            If pfBitmap <> PixelFormat.Format24bppRgb And _
                pfBitmap <> PixelFormat.Format32bppRgb And _
                pfBitmap <> PixelFormat.Format32bppArgb Then
                MsgBox("Bitmap的颜色深度格式无法转换。")
                Exit Function
            End If

            iBmpWidth = bmpPicData.Width
            iBmpHeight = bmpPicData.Height

            'Bitmapの矩形サイズ定義
            Dim rectBmp As New Rectangle(0, 0, iBmpWidth, iBmpHeight)

            'BitmapをBitmapDataに定義・コピーに備えてLockする  
            Dim bmpData As Imaging.BitmapData = bmpPicData.LockBits(rectBmp, _
                Imaging.ImageLockMode.ReadWrite, bmpPicData.PixelFormat)

            'BitmapDataのポインタを取得
            Dim ptrBmpData As IntPtr = bmpData.Scan0

            'Bitmapの横幅データサイズ×Bitmapの高さ＝全体のデータサイズ
            Dim iBytes As Integer = bmpData.Stride * iBmpHeight

            'BitmapDataをコピーされる作業用1次元配列のサイズを定義
            ReDim ByteRgbValues(iBytes - 1)

            'Bitmapの1ピクセルあたりのデータサイズを計算
            Dim iBytePerPixel As Integer = CInt(bmpData.Stride / iBmpWidth)

            'BitmapDataを作業用1次元配列にコピーする
            Marshal.Copy(ptrBmpData, ByteRgbValues, 0, iBytes)

            'BitmapDataを Unlock
            bmpPicData.UnlockBits(bmpData)

            '戻り値のRGB配列の大きさをBitmapデータに合わせて変更
            ReDim argbPicData(bmpPicData.Width - 1, bmpPicData.Height - 1)

            '作業用1次元配列からARGB2次元配列にコピー
            'コピー先のαチャンネルは試用しないので無視、RGBのみコピー
            For iPosY = 0 To iBmpHeight - 1
                For iPosX = 0 To iBmpWidth - 1
                    'カラー画像
                    iOfset = (iPosX + (iPosY * iBmpWidth)) * iBytePerPixel
                    argbPicData(iPosX, iPosY).B = ByteRgbValues(iOfset)
                    argbPicData(iPosX, iPosY).G = ByteRgbValues(iOfset + 1)
                    argbPicData(iPosX, iPosY).R = ByteRgbValues(iOfset + 2)
                    argbPicData(iPosX, iPosY).A = 0
                Next
            Next
            BitmapToArgb = True

        Catch ex As Exception
            MsgBox(ex.ToString & ControlChars.CrLf & ControlChars.CrLf & _
                     "Bitmapからピクセルデータを取得でエラー発生。", , "BitmapToArgb")
        End Try

        Erase ByteRgbValues
    End Function


    '////////////////////////////////////////////////////////////////////
    '// ArgbDataToBitmap - Argb型カラー画像データからBitmapオブジェクトに変換
    '//             by Hidemi Otaki
    '////////////////////////////////////////////////////////////////////
    Public Function ArgbToBitmap(ByRef argbPicData(,) As ArgbData, _
                                ByRef bmpPicData As Bitmap) As Boolean
        'ARGB配列データをBitmapにコピー
        '元画像は32bitカラーARGBデータ→32bitカラーARGB Bitmap)
        Dim iOfset As Integer
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataWidth As Integer
        Dim iDataHeight As Integer
        Dim iBmpWidth As Integer
        Dim iBmpHeight As Integer
        Dim ByteRgbValues() As Byte

        ArgbToBitmap = False

        Try
            'RGB2次元配列のサイズを取得
            iDataWidth = UBound(argbPicData, 1) + 1
            iDataHeight = UBound(argbPicData, 2) + 1

            'Bitmapにコピーするためのargbデータ配列のサイズを設定。
            'ただし、幅は4の倍数にすること
            iBmpWidth = iDataWidth
            iBmpHeight = iDataHeight
            If (iDataWidth Mod 4) <> 0 Then
                iBmpWidth = iDataWidth - (iDataWidth Mod 4) + 4
            End If

            'Bitmapの横幅データサイズ×Bitmapの高さ×1ピクセルのバイト数＝全体のデータサイズ
            Dim iBytes As Integer = iBmpWidth * iBmpHeight * 3

            'RGBデータをBitmapにコピーするための作業用1次元配列のサイズを定義
            ReDim ByteRgbValues(iBytes - 1)

            'RGB2次元配列から作業用1次元配列にコピー
            For iPosY = 0 To iBmpHeight - 1
                For iPosX = 0 To iBmpWidth - 1
                    iOfset = (iPosX + (iPosY * iBmpWidth)) * 3
                    If iPosX < iDataWidth Then
                        '画像データコピー
                        ByteRgbValues(iOfset) = argbPicData(iPosX, iPosY).B
                        ByteRgbValues(iOfset + 1) = argbPicData(iPosX, iPosY).G
                        ByteRgbValues(iOfset + 2) = argbPicData(iPosX, iPosY).R
                    Else
                        '足りない部分の画像を右端のデータで置き換え
                        ByteRgbValues(iOfset) = argbPicData(iDataWidth - 1, iPosY).B
                        ByteRgbValues(iOfset + 1) = argbPicData(iDataWidth - 1, iPosY).G
                        ByteRgbValues(iOfset + 2) = argbPicData(iDataWidth - 1, iPosY).R
                    End If
                Next
            Next

            'BitmapをRGB2次元配列の大きさに合わせる
            bmpPicData = New Bitmap(iBmpWidth, iBmpHeight, Drawing.Imaging.PixelFormat.Format24bppRgb)  'Color32bit/ピクセル 

            'Bitmapの矩形サイズ定義
            Dim rectBmp As New Rectangle(0, 0, iBmpWidth, iBmpHeight)

            'BitmapをBitmapDataに定義・コピーに備えてLockする  
            Dim bmpData As Imaging.BitmapData = bmpPicData.LockBits(rectBmp, _
                Imaging.ImageLockMode.ReadWrite, bmpPicData.PixelFormat)

            'BitmapDataのポインタを取得
            Dim ptrBmpData As IntPtr = bmpData.Scan0

            '作業用1次元配列からBitmapDataにコピーする
            Marshal.Copy(ByteRgbValues, 0, ptrBmpData, iBytes)

            'BitmapDataを Unlock
            bmpPicData.UnlockBits(bmpData)

            ArgbToBitmap = True

        Catch ex As Exception
            MsgBox(ex.ToString & ControlChars.CrLf & ControlChars.CrLf & _
                     "BMP文件生成失败", , "ArgbToBitmap")
        End Try

        Erase ByteRgbValues

    End Function

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        TextBox1.Text = ""
    End Sub


    'カラー画像をグレースケールに変換（Byte型の別配列で返す）
    Public Function ArgbToByte(ByRef argbPicData(,) As ArgbData, _
                                ByRef bytePicData(,) As Byte) As Boolean
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataSizeX As Integer
        Dim iDataSizeY As Integer
        Dim dKido As Double

        ArgbToByte = False

        Try
            'RGB2次元配列のサイズを取得
            iDataSizeX = UBound(argbPicData, 1)
            iDataSizeY = UBound(argbPicData, 2)
            ReDim bytePicData(iDataSizeX, iDataSizeY)

            For iPosY = 0 To iDataSizeY
                For iPosX = 0 To iDataSizeX
                    '加重平均による輝度値算出
                    dKido = CDbl(argbPicData(iPosX, iPosY).R) * 0.2988 + _
                              CDbl(argbPicData(iPosX, iPosY).G) * 0.5868 + _
                              CDbl(argbPicData(iPosX, iPosY).B) * 0.1144
                    bytePicData(iPosX, iPosY) = RGBRange(CInt(dKido))
                Next
            Next

            ArgbToByte = True

        Catch ex As Exception
            MsgBox("文件像素转换失败。" & _
                    ControlChars.CrLf & ex.Message, , "ArgbToByte")
        End Try
    End Function



    'カラー画像をグレースケールに変換（Double型の別配列で返す）
    Public Function ArgbToDouble(ByRef argbPicData(,) As ArgbData, _
                                    ByRef dPicData(,) As Double) As Boolean
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataSizeX As Integer
        Dim iDataSizeY As Integer

        ArgbToDouble = False

        Try
            'RGB2次元配列のサイズを取得
            iDataSizeX = UBound(argbPicData, 1)
            iDataSizeY = UBound(argbPicData, 2)
            ReDim dPicData(iDataSizeX, iDataSizeY)

            For iPosY = 0 To iDataSizeY
                For iPosX = 0 To iDataSizeX
                    '加重平均による輝度値算出
                    dPicData(iPosX, iPosY) = CDbl(argbPicData(iPosX, iPosY).R) * 0.2988 + _
                                                CDbl(argbPicData(iPosX, iPosY).G) * 0.5868 + _
                                                CDbl(argbPicData(iPosX, iPosY).B) * 0.1144
                Next
            Next

            ArgbToDouble = True

        Catch ex As Exception
            MsgBox("彩色图片灰度化失败。" & _
                    ControlChars.CrLf & ex.Message, , "ArgbToDouble")
        End Try
    End Function



    'Argb型カラー画像を2値化画像に変換（Byte型の別配列で返す）
    Public Function ArgbToBin(ByRef argbPicData(,) As ArgbData, _
                                ByRef bytePicData(,) As Byte, _
                                ByVal byteThresh As Byte, _
                                Optional ByVal bInvert As Boolean = False) As Boolean
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataSizeX As Integer
        Dim iDataSizeY As Integer
        Dim dKido As Double
        Dim byteKido As Byte

        ArgbToBin = False

        Try
            'RGB2次元配列のサイズを取得
            iDataSizeX = UBound(argbPicData, 1)
            iDataSizeY = UBound(argbPicData, 2)
            ReDim bytePicData(iDataSizeX, iDataSizeY)

            For iPosY = 0 To iDataSizeY
                For iPosX = 0 To iDataSizeX
                    '加重平均による輝度値算出
                    dKido = CDbl(argbPicData(iPosX, iPosY).R) * 0.2988 + _
                              CDbl(argbPicData(iPosX, iPosY).G) * 0.5868 + _
                              CDbl(argbPicData(iPosX, iPosY).B) * 0.1144
                    byteKido = RGBRange(CInt(dKido))
                    Select Case bInvert
                        Case False
                            'スレッシュより暗い部分を黒に（明るい部分を白に）
                            If byteKido <= byteThresh Then
                                bytePicData(iPosX, iPosY) = 0
                            Else
                                bytePicData(iPosX, iPosY) = 255
                            End If
                        Case True
                            'スレッシュより暗い部分を白に（明るい部分を黒に）
                            If byteKido <= byteThresh Then
                                bytePicData(iPosX, iPosY) = 255
                            Else
                                bytePicData(iPosX, iPosY) = 0
                            End If
                    End Select
                Next
            Next

            ArgbToBin = True

        Catch ex As Exception
            MsgBox("彩色文件转换失败。" & _
                    ControlChars.CrLf & ex.Message, , "ArgbToBin")
        End Try
    End Function


    'Byte型グレー画像を2値化画像に変換（同じ配列で返す）
    Public Function ByteToBin(ByRef bytePicData(,) As Byte, _
                                ByVal byteThresh As Byte, _
                                Optional ByVal bInvert As Boolean = False, _
                                Optional ByVal iAveDelta As Integer = 5) As Boolean
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataSizeX As Integer
        Dim iDataSizeY As Integer

        ByteToBin = False

        Try
            'RGB2次元配列のサイズを取得
            iDataSizeX = UBound(bytePicData, 1)
            iDataSizeY = UBound(bytePicData, 2)

            If byteThresh = 0 Then
                byteThresh = GetBinThresh(bytePicData, , , , iAveDelta)  'デフォルトは平均輝度-5
            End If
            If byteThresh = 0 Then
                byteThresh = GetBinThresh(bytePicData)  'デフォルトは平均輝度-5
            End If

            For iPosY = 0 To iDataSizeY
                For iPosX = 0 To iDataSizeX
                    Select Case bInvert
                        Case False
                            'スレッシュより暗い部分を黒に
                            If bytePicData(iPosX, iPosY) <= byteThresh Then
                                bytePicData(iPosX, iPosY) = 0
                            Else
                                bytePicData(iPosX, iPosY) = 255
                            End If
                        Case True
                            'スレッシュより明るい部分を黒に
                            If bytePicData(iPosX, iPosY) >= byteThresh Then
                                bytePicData(iPosX, iPosY) = 0
                            Else
                                bytePicData(iPosX, iPosY) = 255
                            End If
                    End Select
                Next
            Next

            ByteToBin = True

        Catch ex As Exception
            MsgBox("Byte型灰度文件转换失败。" & _
                    ControlChars.CrLf & ex.Message, , "ByteToBin")
        End Try
    End Function

    'Byte型のモノクロ画像データ、2次元配列同士のコピー
    Public Function CopyByteArray(ByRef byteSrcPicData(,) As Byte, _
                                    ByRef byteDstPicData(,) As Byte, _
                                    Optional ByVal iCipStartX As Integer = 0, _
                                    Optional ByVal iCipStartY As Integer = 0, _
                                    Optional ByVal iCipWidth As Integer = 0, _
                                    Optional ByVal iClipHeight As Integer = 0) As Boolean
        'Byte型のモノクロ画像データ、2次元配列同士でサイズを変換せずにコピーする
        'オプションで希望範囲を切り出すことも可能
        Dim iClipEndX As Integer
        Dim iClipEndY As Integer
        Dim iSrcPosX As Integer
        Dim iSrcPosY As Integer
        Dim iDstPosX As Integer
        Dim iDstPosY As Integer

        CopyByteArray = False
        Try
            'コピーサイズの指定がない場合は元の2次元配列のサイズから算出
            If iCipWidth = 0 Then
                iCipWidth = UBound(byteSrcPicData, 1) - iCipStartX + 1
            End If
            If iClipHeight = 0 Then
                iClipHeight = UBound(byteSrcPicData, 2) - iCipStartY + 1
            End If

            iClipEndX = iCipStartX + iCipWidth - 1
            iClipEndY = iCipStartY + iClipHeight - 1
            ReDim byteDstPicData(iCipWidth - 1, iClipHeight - 1)

            For iSrcPosY = iCipStartY To iClipEndY
                For iSrcPosX = iCipStartX To iClipEndX
                    iDstPosX = iSrcPosX - iCipStartX
                    iDstPosY = iSrcPosY - iCipStartY
                    byteDstPicData(iDstPosX, iDstPosY) = byteSrcPicData(iSrcPosX, iSrcPosY)
                Next
            Next

            CopyByteArray = True

        Catch ex As Exception
            MsgBox("Byte型灰度画像转换失败。" & _
                    ControlChars.CrLf & ex.Message, , "CopyByteArray")
        End Try
    End Function

    'Byte型グレー画像を、スレッシュを自動で計算して2値化画像に変換（別の配列で返す）
    Public Function ByteAutoBin(ByRef bytePicData(,) As Byte, _
                                ByRef byteBinData(,) As Byte, _
                                Optional ByVal iAveDelta As Integer = 5, _
                                Optional ByVal iBlackRatio As Integer = 10, _
                                Optional ByVal iCornerChkPixel As Integer = 5, _
                                Optional ByVal iRefCornerBlackCount As Integer = 4, _
                                Optional ByVal bInvert As Boolean = False) As Boolean
        Dim bRtn As Boolean
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataSizeX As Integer
        Dim iDataSizeY As Integer
        Dim iRefBlackCount As Integer
        Dim iBlackCount As Integer
        Dim iCornerBlackCount As Integer
        Dim iPixCount As Integer
        Dim byteThresh As Byte

        ByteAutoBin = False

        Try
            'RGB2次元配列のサイズを取得
            iDataSizeX = UBound(bytePicData, 1)
            iDataSizeY = UBound(bytePicData, 2)
            ReDim byteBinData(iDataSizeX, iDataSizeY)

            '画面の中で黒で良い画素数割合（スレッシュ可変用）
            iRefBlackCount = CInt(iDataSizeX * iDataSizeY * iBlackRatio / 100)

            If byteThresh = 0 Then
                byteThresh = GetBinThresh(bytePicData, , , , iAveDelta)  'デフォルトは平均輝度-5
            End If

            Do
                '画像データを作業用画像データにコピーする
                bRtn = CopyByteArray(bytePicData, byteBinData)

                iBlackCount = 0
                iPixCount = 0
                For iPosY = 0 To iDataSizeY
                    For iPosX = 0 To iDataSizeX
                        Select Case bInvert
                            Case False
                                'スレッシュより暗い部分を黒に
                                If byteBinData(iPosX, iPosY) <= byteThresh Then
                                    byteBinData(iPosX, iPosY) = 0
                                    iBlackCount += 1
                                Else
                                    byteBinData(iPosX, iPosY) = 255
                                End If
                            Case True
                                'スレッシュより明るい部分を黒に
                                If byteBinData(iPosX, iPosY) >= byteThresh Then
                                    byteBinData(iPosX, iPosY) = 0
                                    iBlackCount += 1
                                Else
                                    byteBinData(iPosX, iPosY) = 255
                                End If
                        End Select
                        If iBlackCount > iRefBlackCount Then Exit For
                    Next
                    If iBlackCount > iRefBlackCount Then Exit For
                Next

                '2値化処理終了Pixel数
                iPixCount = (iPosX - 1) * (iPosY - 1)

                '4隅の角のiCornerChkPixel×iCornerChkPixelの範囲を確認
                If iBlackCount < iRefBlackCount Then
                    iCornerBlackCount = 0
                    For iPosY = 0 To iCornerChkPixel - 1
                        For iPosX = 0 To iCornerChkPixel - 1
                            If byteBinData(iPosX, iPosY) = 0 Then iCornerBlackCount += 1
                            If byteBinData(iDataSizeX - iPosX, iPosY) = 0 Then iCornerBlackCount += 1
                            If byteBinData(iPosX, iDataSizeY - iPosY) = 0 Then iCornerBlackCount += 1
                            If byteBinData(iDataSizeX - iPosX, iDataSizeY - iPosY) = 0 Then iCornerBlackCount += 1
                        Next
                    Next
                End If
                Select Case bInvert
                    Case False
                        If byteThresh > iAveDelta Then
                            byteThresh -= CByte(iAveDelta)
                        Else
                            MsgBox("二值化失败。" & _
                                    ControlChars.CrLf & "没有探测到合适的阈值。", , "ByteAutoBin")
                            Exit Function
                        End If
                    Case True
                        If 255 - byteThresh > iAveDelta Then
                            byteThresh += CByte(iAveDelta)
                        Else
                            MsgBox("二值化失败。" & _
                                    ControlChars.CrLf & "没有探测到合适的阈值。", , "ByteAutoBin")
                            Exit Function
                        End If
                End Select

            Loop Until iPixCount = iDataSizeX * iDataSizeY And iCornerBlackCount < iRefCornerBlackCount

            ByteAutoBin = True

        Catch ex As Exception
            MsgBox("二值化图片失败。" & _
                    ControlChars.CrLf & ex.Message, , "ByteAutoBin")
        End Try
    End Function

    'Byte型グレー画像を2値化する際の、スレッシュレベルの目安を得る関数
    Public Function GetBinThresh(ByRef bytePicData(,) As Byte, _
                                    Optional ByRef byteAveData As Byte = 0, _
                                    Optional ByRef byteMaxData As Byte = 0, _
                                    Optional ByRef byteMinData As Byte = 0, _
                                    Optional ByVal iAveDelta As Integer = 5) As Byte
        Dim iPosX As Integer
        Dim iPosY As Integer
        Dim iDataSizeX As Integer
        Dim iDataSizeY As Integer
        Dim iSumData As Integer

        GetBinThresh = 0

        Try
            'RGB2次元配列のサイズを取得
            iDataSizeX = UBound(bytePicData, 1)
            iDataSizeY = UBound(bytePicData, 2)

            iSumData = 0
            For iPosX = 0 To iDataSizeX
                iSumData += bytePicData(iPosX, CInt(iDataSizeY / 2))
            Next
            For iPosY = 0 To iDataSizeY
                iSumData += bytePicData(CInt(iDataSizeX / 2), iPosY)
            Next

            byteMaxData = 0
            byteMinData = 255
            For iPosY = 0 To iDataSizeY
                For iPosX = 0 To iDataSizeX
                    If byteMaxData < bytePicData(iPosX, iPosY) Then
                        byteMaxData = bytePicData(iPosX, iPosY)
                    End If
                    If byteMinData > bytePicData(iPosX, iPosY) Then
                        byteMinData = bytePicData(iPosX, iPosY)
                    End If
                Next
            Next
            byteAveData = CByte(iSumData / (iDataSizeX + iDataSizeY))

            If byteAveData > CByte(iAveDelta) Then
                GetBinThresh = byteAveData - CByte(iAveDelta)
            Else
                GetBinThresh = byteAveData
            End If

        Catch ex As Exception
            MsgBox("灰度图片二值化失败。" & _
                    ControlChars.CrLf & ex.Message, , "GetBinThresh")
        End Try

    End Function


    Private Sub btnOpenCamera_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpenCamera.Click
        Try

            'GetDeviceList()

            'If (videoSource Is Nothing) Then
            '    GetDeviceList()
            'End If

            '(cmbCameraList.SelectedIndex)

            DoShowImage()
            If videoDevices.Count <> 0 Then
                btnStart.Enabled = True
                Button1.Enabled = True
                cmbCameraList.Enabled = False
                btnSearchCamera.Enabled = False
            End If

        Catch ex As Exception
            btnStart.Enabled = False
            Button1.Enabled = False
            MsgBox("摄像头启动失败")
        End Try
    End Sub
    Public Sub videoSource_NewFrame(ByVal sender As Object, ByVal eventArgs As AForge.Video.NewFrameEventArgs) Handles videoSource.NewFrame

        CaptureFrame = eventArgs.Frame.Clone()
        picboxMain.Image = CaptureFrame
        'picboxMain.Refresh()

    End Sub
    Public Sub GetDeviceList()
        Try
            videoDevices = New FilterInfoCollection(FilterCategory.VideoInputDevice)
            If videoDevices.Count = 0 Then
                Throw New ApplicationException()
            Else
                cmbCameraList.Items.Clear()
                For i As Integer = 0 To videoDevices.Count - 1
                    cmbCameraList.Items.Add(videoDevices(i).Name)
                Next

                cmbCameraList.SelectedIndex = 0
            End If
        Catch ex As Exception
            MessageBox.Show("未找到有效的摄像头")
        End Try

    End Sub



    Public Sub DoShowImage()
        Try
            If videoDevices.Count <> 0 Then
                ' If videoSource Is Nothing Then
                'videoSource = New VideoCaptureDevice(videoDevices(0).MonikerString)
                videoSource = New VideoCaptureDevice(videoDevices(cmbCameraList.SelectedIndex).MonikerString)
                'End If

                If Not videoSource.IsRunning Then
                    videoSource.Start()
                End If
            End If
        Catch ex As Exception
            MessageBox.Show("指定的摄像头" & cmbCameraList.SelectedText & "启动失败")
        End Try




    End Sub

    Private Sub btnCal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEndCal.Click
        btnStart.Enabled = True
        Button1.Enabled = True
        btnEndCal.Enabled = False
        'Timer1.Enabled = False
        Timer1.Stop()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        startCal()
    End Sub

    Private Sub chkBoxEnablePhase2_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkBoxEnablePhase2.CheckedChanged
        txtBoxSpec2.Enabled = chkBoxEnablePhase2.Checked
        picBoxPhase2.Visible = chkBoxEnablePhase2.Checked
        txtCurrentResultPhase2.Visible = chkBoxEnablePhase2.Checked
    End Sub

    Private Sub chkBoxEnablePhase1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkBoxEnablePhase1.CheckedChanged
        txtBoxSpec1.Enabled = chkBoxEnablePhase1.Checked
        picBoxPhase1.Visible = chkBoxEnablePhase1.Checked
        txtCurrentResultPhase1.Visible = chkBoxEnablePhase1.Checked
    End Sub

    Private Sub chkBoxEnablePhaseCenter_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkBoxEnablePhaseCenter.CheckedChanged
        txtBoxSpecCenter.Enabled = chkBoxEnablePhaseCenter.Checked
        picBoxPhaseCenter.Visible = chkBoxEnablePhaseCenter.Checked
        txtCurrentResultPhaseCenter.Visible = chkBoxEnablePhaseCenter.Checked
    End Sub

    Private Sub chkBoxEnablePhase3_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkBoxEnablePhase3.CheckedChanged
        txtBoxSpec3.Enabled = chkBoxEnablePhase3.Checked
        picBoxPhase3.Visible = chkBoxEnablePhase3.Checked
        txtCurrentResultPhase3.Visible = chkBoxEnablePhase3.Checked
    End Sub

    Private Sub chkBoxEnablePhase4_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkBoxEnablePhase4.CheckedChanged
        txtBoxSpec4.Enabled = chkBoxEnablePhase4.Checked
        picBoxPhase4.Visible = chkBoxEnablePhase4.Checked
        txtCurrentResultPhase4.Visible = chkBoxEnablePhase4.Checked
    End Sub

    Private Sub chkBoxDrawResult_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkBoxDrawResult.CheckedChanged
        picBoxPhase1.Visible = chkBoxDrawResult.Checked
        picBoxPhase2.Visible = chkBoxDrawResult.Checked
        picBoxPhase3.Visible = chkBoxDrawResult.Checked
        picBoxPhase4.Visible = chkBoxDrawResult.Checked
        picBoxPhaseCenter.Visible = chkBoxDrawResult.Checked

    End Sub
    Public Sub initBrush()
        Dim cr As Double
        Dim cg As Double
        Dim cb As Double

        If radBT709.Checked Then
            cr = 0.2125
            cg = 0.7154
            cb = 0.0721
        End If

        If radRMY.Checked Then
            cr = 0.5
            cg = 0.419
            cb = 0.08
        End If

        If radBT709.Checked Then
            cr = 0.299
            cg = 0.587
            cb = 0.114
        End If

        filter = New AForge.Imaging.Filters.Grayscale(cr, cg, cb)
    End Sub

    Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim CalTime As Long = 0
        initBrush()

        Dim StartTime As DateTime = Now
        startCal()

        Dim TS As TimeSpan = Now.Subtract(StartTime)

        CalTime = TS.TotalMilliseconds.ToString

        labCalTime.Text = CalTime.ToString & " (ms)毫秒"

        bSampleImageInit = saveSampleImage()

    End Sub

    Public Sub saveAreaInfo()
        Dim writer As New System.Xml.Serialization.XmlSerializer(GetType(AreaInfo))
        Dim file As StreamWriter
        file = New System.IO.StreamWriter("AreaInfoPhease1.xml")
        writer.Serialize(file, areaPhase1)
        file.Close()

        file = New System.IO.StreamWriter("AreaInfoPhease2.xml")
        writer.Serialize(file, areaPhase2)
        file.Close()

        file = New System.IO.StreamWriter("AreaInfoPhease3.xml")
        writer.Serialize(file, areaPhase3)
        file.Close()

        file = New System.IO.StreamWriter("AreaInfoPhease4.xml")
        writer.Serialize(file, areaPhase4)
        file.Close()

        file = New System.IO.StreamWriter("AreaInfoPheaseCenter.xml")
        writer.Serialize(file, areaPhaseCenter)
        file.Close()
    End Sub

    Public Sub ReadAreaInfo()
        Dim reader As New System.Xml.Serialization.XmlSerializer(GetType(AreaInfo))
        Dim file As System.IO.StreamReader
        file = New System.IO.StreamReader("AreaInfoPhease1.xml")
        areaPhase1 = CType(reader.Deserialize(file), AreaInfo)
        file.Close()

        file = New System.IO.StreamReader("AreaInfoPhease2.xml")
        areaPhase2 = CType(reader.Deserialize(file), AreaInfo)
        file.Close()

        file = New System.IO.StreamReader("AreaInfoPhease3.xml")
        areaPhase3 = CType(reader.Deserialize(file), AreaInfo)
        file.Close()

        file = New System.IO.StreamReader("AreaInfoPhease4.xml")
        areaPhase4 = CType(reader.Deserialize(file), AreaInfo)
        file.Close()

        file = New System.IO.StreamReader("AreaInfoPheaseCenter.xml")
        areaPhaseCenter = CType(reader.Deserialize(file), AreaInfo)
        file.Close()

    End Sub

    Private Sub btnCloseCamera_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCloseCamera.Click
        Timer1.Stop()
        If (videoSource Is Nothing) Then
            MsgBox("摄像头未启动")
        Else
            If videoSource.IsRunning Then
                videoSource.SignalToStop()
                picboxMain.Image = Nothing
                btnStart.Enabled = False
                btnEndCal.Enabled = False
                Button1.Enabled = False
                cmbCameraList.Enabled = True
                btnSearchCamera.Enabled = True
            Else
                MsgBox("摄像头未处于运行状态")
            End If
        End If

    End Sub

    Public Sub fillAreaParam(Optional ByVal isFake As Boolean = False)
        If Not isFake Then
            txtStartXPhase1.Text = areaPhase1.StartPoint.X.ToString
            txtStartYPhase1.Text = areaPhase1.StartPoint.Y.ToString
            txtSizeWPhase1.Text = areaPhase1.AreaSize.Width.ToString
            txtSizeHPhase1.Text = areaPhase1.AreaSize.Height.ToString

            txtStartXPhase2.Text = areaPhase2.StartPoint.X.ToString
            txtStartYPhase2.Text = areaPhase2.StartPoint.Y.ToString
            txtSizeWPhase2.Text = areaPhase2.AreaSize.Width.ToString
            txtSizeHPhase2.Text = areaPhase2.AreaSize.Height.ToString

            txtStartXPhase3.Text = areaPhase3.StartPoint.X.ToString
            txtStartYPhase3.Text = areaPhase3.StartPoint.Y.ToString
            txtSizeWPhase3.Text = areaPhase3.AreaSize.Width.ToString
            txtSizeHPhase3.Text = areaPhase3.AreaSize.Height.ToString

            txtStartXPhase4.Text = areaPhase4.StartPoint.X.ToString
            txtStartYPhase4.Text = areaPhase4.StartPoint.Y.ToString
            txtSizeWPhase4.Text = areaPhase4.AreaSize.Width.ToString
            txtSizeHPhase4.Text = areaPhase4.AreaSize.Height.ToString

            txtStartXPhaseCenter.Text = areaPhaseCenter.StartPoint.X.ToString
            txtStartYPhaseCenter.Text = areaPhaseCenter.StartPoint.Y.ToString
            txtSizeWPhaseCenter.Text = areaPhaseCenter.AreaSize.Width.ToString
            txtSizeHPhaseCenter.Text = areaPhaseCenter.AreaSize.Height.ToString
        Else
            areaPhase1.StartPoint.X = 1
            areaPhase1.StartPoint.Y = 1
            areaPhase1.AreaSize.Width = 1
            areaPhase1.AreaSize.Height = 1

            areaPhase2 = areaPhase1
            areaPhase3 = areaPhase1
            areaPhase4 = areaPhase1
            areaPhaseCenter = areaPhase1
        End If

    End Sub

    Public Sub setAreaStruct()
        areaPhase1.StartPoint.X = CInt(txtStartXPhase1.Text)
        areaPhase1.StartPoint.Y = CInt(txtStartYPhase1.Text)
        areaPhase1.AreaSize.Width = CInt(txtSizeWPhase1.Text)
        areaPhase1.AreaSize.Height = CInt(txtSizeHPhase1.Text)

        areaPhase2.StartPoint.X = CInt(txtStartXPhase2.Text)
        areaPhase2.StartPoint.Y = CInt(txtStartYPhase2.Text)
        areaPhase2.AreaSize.Width = CInt(txtSizeWPhase2.Text)
        areaPhase2.AreaSize.Height = CInt(txtSizeHPhase2.Text)

        areaPhase3.StartPoint.X = CInt(txtStartXPhase3.Text)
        areaPhase3.StartPoint.Y = CInt(txtStartYPhase3.Text)
        areaPhase3.AreaSize.Width = CInt(txtSizeWPhase3.Text)
        areaPhase3.AreaSize.Height = CInt(txtSizeHPhase3.Text)

        areaPhase4.StartPoint.X = CInt(txtStartXPhase4.Text)
        areaPhase4.StartPoint.Y = CInt(txtStartYPhase4.Text)
        areaPhase4.AreaSize.Width = CInt(txtSizeWPhase4.Text)
        areaPhase4.AreaSize.Height = CInt(txtSizeHPhase4.Text)

        areaPhaseCenter.StartPoint.X = CInt(txtStartXPhaseCenter.Text)
        areaPhaseCenter.StartPoint.Y = CInt(txtStartYPhaseCenter.Text)
        areaPhaseCenter.AreaSize.Width = CInt(txtSizeWPhaseCenter.Text)
        areaPhaseCenter.AreaSize.Height = CInt(txtSizeHPhaseCenter.Text)

    End Sub



    Private Sub btnSaveCurrentPara_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSaveCurrentPara.Click
        setAreaStruct()
        saveAreaInfo()
        syncAreaInfo()
    End Sub

    Private Sub btnReadCurrentPara_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReadCurrentPara.Click
        ReadAreaInfo()
        fillAreaParam()
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        picboxMain.Image = New Bitmap(TextBox2.Text)
    End Sub
    Public Sub Roberts(ByRef bytePicData(,) As Byte, _
                        ByRef byteBinPicData(,) As Byte, _
                              Optional ByVal kickpoint As Integer = 128 _
                        )

        Dim x As Integer
        Dim y As Integer

        Dim G As Integer


        Dim w As Integer = UBound(bytePicData, 1)
        Dim h As Integer = UBound(bytePicData, 2)
        ReDim byteBinPicData(w, h)

        For x = 1 To w - 1

            For y = 1 To h - 1
                ' G(x,y)=abs(f(x,y)-f(x+1,y+1))+abs(f(x,y+1)-f(x+1,y))

                G = Math.Abs(CInt(bytePicData(x, y)) - CInt(bytePicData(x + 1, y + 1))) + Math.Abs(CInt(bytePicData(x, y + 1)) - CInt(bytePicData(x + 1, y)))

                byteBinPicData(x, y) = RGBRange(G)
            Next y
        Next x

    End Sub

    Public Sub SobelCal(ByRef bytePicData(,) As Byte, _
                        ByRef byteBinPicData(,) As Byte, _
                              Optional ByVal kickpoint As Integer = 128 _
                        )
        Dim x As Integer
        Dim y As Integer
        Dim Gx As Integer
        Dim Gy As Integer
        Dim G As Integer


        Dim w As Integer = UBound(bytePicData, 1)
        Dim h As Integer = UBound(bytePicData, 2)
        ReDim byteBinPicData(w, h)

        For x = 1 To w - 1

            For y = 1 To h - 1

                'Gx = [f(x+1,y-1)+2*f(x+1,y)+f(x+1,y+1)]-[f(x-1,y-1)+2*f(x-1,y)+f(x-1,y+1)]
                Gx = (bytePicData(x + 1, y - 1) + 2 * bytePicData(x + 1, y + 1)) - (bytePicData(x - 1, y - 1) + 2 * bytePicData(x - 1, y) + bytePicData(x - 1, y + 1))

                'Gy =  [f(x-1,y-1) + 2f(x,y-1) + f(x+1,y-1)]-[f(x-1, y+1) + 2*f(x,y+1)+f(x+1,y+1)]
                Gy = (bytePicData(x - 1, y - 1) + 2 * bytePicData(x, y - 1) + bytePicData(x + 1, y - 1)) - (bytePicData(x - 1, y + 1) + 2 * bytePicData(x, y + 1) + bytePicData(x + 1, y + 1))

                'G = (Math.Abs(Gx) + Math.Abs(Gy)) >> 1

                'If Math.Abs(Gx) >= Math.Abs(Gy) Then
                '    G = Math.Abs(Gx)
                'Else
                '    G = Math.Abs(Gy)
                'End If

                G = Math.Sqrt(Gx ^ 2 + Gy ^ 2)

                ' TextBox1.AppendText(G.ToString & vbCrLf)

                '横向梯度
                ' s = src[x + 1 + (y - 1) * width] + 2 * src[x + 1 + (y) * width]+ src[x + 1 + (y + 1) * width]
                '		s = s - src[x - 1 + (y - 1) * width] - 2 * src[x - 1 + (y) * width]- src[x - 1 + (y + 1) * width]


                ''临界值
                'If (s > kickpoint) Then
                '    s = 255
                'Else
                '    s = 0
                'End If

                'byteBinPicData(y * w + x) = s

                byteBinPicData(x, y) = RGBRange(G)
            Next y
        Next x
    End Sub

    Private Sub btnReadSpecPara_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReadSpecPara.Click
        ReadSpecInfo()
        fillSpecValue()
    End Sub

    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        specValue.specValuePhase1 = CInt(txtBoxSpec1.Text)
        specValue.specValuePhase2 = CInt(txtBoxSpec2.Text)
        specValue.specValuePhase3 = CInt(txtBoxSpec3.Text)
        specValue.specValuePhase4 = CInt(txtBoxSpec4.Text)
        specValue.specValuePhaseCenter = CInt(txtBoxSpecCenter.Text)

        specValue.specValueGain = CInt(txtResultGain.Text)

        saveSpecInfo()
    End Sub

    Public Sub saveSpecInfo()
        Dim writer As New System.Xml.Serialization.XmlSerializer(GetType(SpecInfo))
        Dim file As StreamWriter
        file = New System.IO.StreamWriter("SpecInfo.xml")
        writer.Serialize(file, specValue)
        file.Close()

    End Sub

    Public Sub ReadSpecInfo()
        Dim reader As New System.Xml.Serialization.XmlSerializer(GetType(SpecInfo))
        Dim file As System.IO.StreamReader
        file = New System.IO.StreamReader("SpecInfo.xml")
        specValue = CType(reader.Deserialize(file), SpecInfo)
        file.Close()

    End Sub

    Public Sub fillSpecValue()
        txtBoxSpec1.Text = specValue.specValuePhase1.ToString
        txtBoxSpec2.Text = specValue.specValuePhase2.ToString
        txtBoxSpec3.Text = specValue.specValuePhase3.ToString
        txtBoxSpec4.Text = specValue.specValuePhase4.ToString
        txtBoxSpecCenter.Text = specValue.specValuePhaseCenter.ToString
        txtResultGain.Text = specValue.specValueGain.ToString
    End Sub


    Private Sub btnShowAdjForm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShowAdjForm.Click

        If picboxMain.Image Is Nothing Then
            MsgBox("没有启动摄像头读取当前画面，请先启动摄像头")
            Exit Sub
        End If

        adjustForm = New frmAdjust
        adjustForm.Show()
        Me.Enabled = False

    End Sub



    Public Sub drawCheckFrame()

        picboxMain.Refresh()

        'phase1
        gCheckFrame.FillRectangle(frameBrush, New Rectangle(areaForPaintPhase1.StartPoint, areaForPaintPhase1.AreaSize))

        'phase2
        gCheckFrame.FillRectangle(frameBrush, New Rectangle(areaForPaintPhase2.StartPoint, areaForPaintPhase2.AreaSize))

        'phase3
        gCheckFrame.FillRectangle(frameBrush, New Rectangle(areaForPaintPhase3.StartPoint, areaForPaintPhase3.AreaSize))

        'phase4
        gCheckFrame.FillRectangle(frameBrush, New Rectangle(areaForPaintPhase4.StartPoint, areaForPaintPhase4.AreaSize))

        'phaseCenter
        gCheckFrame.FillRectangle(frameBrush, New Rectangle(areaForPaintPhaseCenter.StartPoint, areaForPaintPhaseCenter.AreaSize))

    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        'checkGateStatus()
        TimEnd.Start()


    End Sub

    Private Sub pb1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles pb1.Paint
        Dim pp As Pen = New Pen(Color.Red)
        'e.Graphics.DrawRectangle(pp, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.X + e.ClipRectangle.Width - 1, e.ClipRectangle.Y + e.ClipRectangle.Height - 1)
        'e.Graphics.DrawRectangle(pp, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.X 

        'Draw phase1 Frame
        e.Graphics.DrawRectangle(pp, _
                                 areaForPaintPhase1.StartPoint.X, areaForPaintPhase1.StartPoint.Y, _
                                 areaForPaintPhase1.AreaSize.Width, areaForPaintPhase1.AreaSize.Height)

        'Draw phase2 Frame
        e.Graphics.DrawRectangle(pp, _
                                 areaForPaintPhase2.StartPoint.X, areaForPaintPhase2.StartPoint.Y, _
                                 areaForPaintPhase2.AreaSize.Width, areaForPaintPhase2.AreaSize.Height)

        'Draw phase3 Frame
        e.Graphics.DrawRectangle(pp, _
                                 areaForPaintPhase3.StartPoint.X, areaForPaintPhase3.StartPoint.Y, _
                                 areaForPaintPhase3.AreaSize.Width, areaForPaintPhase3.AreaSize.Height)

        'Draw phase4 Frame
        e.Graphics.DrawRectangle(pp, _
                                 areaForPaintPhase4.StartPoint.X, areaForPaintPhase4.StartPoint.Y, _
                                 areaForPaintPhase4.AreaSize.Width, areaForPaintPhase4.AreaSize.Height)

        'Draw phaseCenter Frame
        e.Graphics.DrawRectangle(pp, _
                                 areaForPaintPhaseCenter.StartPoint.X, areaForPaintPhaseCenter.StartPoint.Y, _
                                 areaForPaintPhaseCenter.AreaSize.Width, areaForPaintPhaseCenter.AreaSize.Height)

    End Sub

    Private Sub TimGate_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimGate.Tick
        'Timer1.Stop()
        checkGateStatus()

        '(1 min ~ 10 min)
        TimGate.Interval = CInt(540000 * Math.Round(Now.Millisecond)) + 60000
        TimGate.Start()
        'Timer1.Start()

    End Sub

    Private Sub btnSearchCamera_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearchCamera.Click
        If (videoSource Is Nothing) Then
            GetDeviceList()
        End If
    End Sub

    Private Sub TimEnd_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimEnd.Tick
        End
    End Sub

    Private Sub TimAdminLock_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimAdminLock.Tick
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedSingle
        TabControl1.Visible = False
        AdminCheck = False
    End Sub

    Private Sub Label17_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label17.DoubleClick
        If AdminCheck = False Then
            If InputBox("Administrator Password:", "Administrator Check") = "wsy" Then
                Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Sizable
                TabControl1.Visible = True
                AdminCheck = True
                TimAdminLock.Start()
            End If
        End If
    End Sub
End Class
